#include "opencv.h"
#include "ui_opencv.h"
#include <chrono>
#include <QFile>
Opencv::Opencv(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Opencv)
{
    ui->setupUi(this);

    QFile qss_file(":/qss/style/opencv.qss"); // 使用资源系统来加载，如果是普通路径，请调整
    if (qss_file.open(QFile::ReadOnly)) {
        QString qss_text = QLatin1String(qss_file.readAll());
        this->setStyleSheet(qss_text);
        qss_file.close();
    }

    timer1 = new QTimer(this);

    // 提前刷新显式控件
    timeoutSlot1();

    timer1->setInterval(500);   // 设置时间间隔1秒钟
    timer1->setSingleShot(false);    // 为周期循环

    // 连接信号槽要在启动定时器之前连接
    connect(timer1,SIGNAL(timeout()),this,
            SLOT(timeoutSlot1()));

    // 启动定时器
    timer1->start();
    connect(ui->pushButtonOpen,SIGNAL(clicked()),this,SLOT(onMonitoring())); //点击开启监控，摄像头打开
    connect(ui->pushButtonClean,SIGNAL(clicked()),this,SLOT(onMonitoring()));//点击关闭监控，摄像头关闭
    connect(ui->pushButtonKaCha,SIGNAL(clicked()),this,SLOT(onMonitoring()));//点击截图按钮，截取图片并保存
}

Opencv::~Opencv()
{
    // 如果正在运行，则先关闭
    if(timer->isActive())
    {
        timer->stop();
    }

    delete timer;
    delete ui;
}

void Opencv::timeoutSlot()
{
    // 从摄像头中获取图像帧
    cap >> src;
    if(!src.data)   // 如果没有数据，表示读取失败
    {
        qDebug() << "读取图片失败";
        return;
    }

    // 灰度处理
    Mat gray;
    // cvtColor:转换颜色空间
    // 参数1：src原始图像数据
    // 参数2：转换后的图像数据
    // 参数3：转换方式
    cvtColor(src,gray,COLOR_BGR2GRAY);

    // 通过级联分类器在黑白图像中查找人脸
    // 参数1：灰度之后的图像数据
    // 参数2：查找到的人脸存储器
    classifier.detectMultiScale(gray,faces);

    for(int i = 0; static_cast<int>(faces.size()) > i;i++)//static_cast<int>：优化有符号整数和无符号整数之间的比较操作警告问题
    {
        // 在原图上标定出人脸
        // 参数1：原始图像数据
        // 参数2：需要标定的第几张人脸
        // 参数3：标定框的颜色【BGR】
        // 参数4：框的线条粗度
        rectangle(src,faces[i],Scalar(255,0,0),3);
    }

    // 展示图像
    // BGR -> RGB
    Mat rgb;
    cvtColor(src,rgb,CV_BGR2RGB);

    // Mat -> QImage
    // 参数1：原始数据
    // 参数2：宽度
    // 参数3：高度
    // 参数4：每一行的总通道数= 宽度*3（rgb的通道数）
    // 参数5：转换格式
    QImage img(rgb.data,rgb.cols,rgb.rows,rgb.cols*3,QImage::Format_RGB888);

    // QImage -> QPixmap
    QPixmap p = QPixmap::fromImage(img);

    // 设置给QLabel
    ui->label->resize(p.width(),p.height());
    ui->label->setPixmap(p);
}
//监控的控制
void Opencv::onMonitoring()
{
    if(sender() == ui->pushButtonOpen)
    {
        //屏蔽开启按钮并修改文字内容
        ui->pushButtonOpen->setEnabled(false);
        ui->pushButtonOpen->setText("已开启监控");
        //释放关闭按钮
        ui->pushButtonClean->setEnabled(true);
        // 加载模型(人脸)
        //级联分类器的初始化： 加载一个数据模型（存放的是什么物体的图片，查找哪类物体）
        classifier = CascadeClassifier("D:/opencv/opencv3.4-install/install/etc/haarcascades/haarcascade_frontalface_alt2.xml");
        if(cap.open(0)) // 0表示默认第一个摄像头
        {
            qDebug() << "摄像头打开成功";
            timer = new QTimer(this);
            timer->setInterval(50); // 50毫秒检测一次
            timer->setSingleShot(false);
            connect(timer,SIGNAL(timeout()),
                    this,SLOT(timeoutSlot()));
            timer->start();
        }
        else
        {
            qDebug() << "打开失败";
        }
    }
    else if(sender() == ui->pushButtonClean)
    {
        //释放连接按钮并修改文字内容
        ui->pushButtonOpen->setEnabled(true);
        ui->pushButtonOpen->setText("开启监控");

        //屏蔽发送和历史按钮
        ui->pushButtonClean->setEnabled(false);

        //关闭定时器
        timer->stop();
        //关闭摄像头
        cap.release();
        ui->label->clear();//清空label里的图片
        ui->labelKaCha->clear();//清空labelKaCha里的图片
        qDebug() <<"摄像头已关闭";
    }
    else if((sender() == ui->pushButtonKaCha) && cap.isOpened() )
    {
        cv::Mat frame;
        cap.read(frame);
        if(frame.empty())
        {
            qDebug() <<"未能成功读到图像帧";
            return;
        }
        //截图保存

        auto now = std::chrono::system_clock::now();
        auto now_time_t = std::chrono::system_clock::to_time_t(now);
        std::string timeStamp = std::ctime(&now_time_t);
        timeStamp = timeStamp.substr(0, timeStamp.length()-1);  // 去掉换行符
        std::replace(timeStamp.begin(), timeStamp.end(), ' ', '_');  // 替换空格
        std::replace(timeStamp.begin(), timeStamp.end(), ':', '-');  // 替换冒号
        std::string fileName = "E:\\photo\\screenshot_" + timeStamp + ".jpg";
        // 保存图像到文件
        if (!cv::imwrite(fileName, frame)) {
            qDebug() << "Error: Failed to save image to " << QString::fromStdString(fileName);
        }
        //   将截取的图像显示在labelKaCha上（以下是简单示例，可能需要进一步处理图像格式等以适配QLabel显示）
        cv::Mat imageToShow;
        cv::resize(frame, imageToShow, cv::Size(500, 500));  // 调整图像大小方便显示，可选操作
        QImage qimg(imageToShow.data, imageToShow.cols, imageToShow.rows, imageToShow.step, QImage::Format_RGB888);
        QPixmap pixmap = QPixmap::fromImage(qimg.rgbSwapped());
        ui->labelKaCha->setPixmap(pixmap);
        qDebug() <<"截图成功";
    }
}

//显示时间
void Opencv::timeoutSlot1()
{
    // 获取当前系统时间，转换为：时:分:秒
    QString str = QDateTime::currentDateTime().toString("hh:mm:ss");
    ui->lcdNumber->display(str);
}


